EP15. 모델 특성에 따른 프롬프트

모든 프롬프트는 모델의 SFT(Supervised Fine-Tuning) 학습 구조와 어텐션 토큰 위치 효과에 정렬되어야 의도대로 작동한다.


0. 사전 필수 용어 (선행지식)

본 단원을 이해하기 위해 다음 5개 용어를 먼저 정리합니다. 입문자는 비유와 함께 빠르게 익히세요.

  1. LLM (Large Language Model) — 텍스트를 입력받아 다음에 올 토큰의 확률 분포를 예측하는 거대 신경망. 비유: "다음 단어 자동완성을 매우 잘하는 기계". 본문 §1~§11 전반에서 가정.
  2. 토큰 (Token) — 모델이 한 번에 처리하는 텍스트 조각 단위 (한글 1~3 글자, 영어 단어 일부). 비유: "조립 블록 한 개". 본문 §3·§6 어텐션 설명에서 사용.
  3. 어텐션 (Attention) — 각 토큰이 다른 모든 토큰을 얼마나 참고할지 학습하는 메커니즘. 비유: "회의에서 누구 말을 더 귀담아 들을지 결정". 본문 §6 핵심 원리.
  4. 파운데이션 모델 (Foundation Model) — 대규모 비지도 사전학습을 거친 1차 모델. SFT 전 단계. 비유: "초중고 일반 교육만 받은 상태". 본문 §1 정의의 전제.
  5. 컴플리션 (Completion) vs 멀티턴 (Multi-turn) — Completion 은 한 덩어리 문자열에 모든 역할이 합쳐진 형식, Multi-turn 은 역할별 메시지가 배열로 분리된 형식. 비유: "장문 편지 한 통" vs "메신저 대화방". 본문 §3 구조 비교.

📚 참고: 선행지식이 부족하면 AI 엔지니어링 EP0 - 선수지식 또는 HuggingFace LLM Course Chapter 1·2 를 먼저 학습합니다.

💡 실무 노하우: SFT 구조는 모델 카드나 tokenizer.chat_template (HF Transformers) 에 명시되어 있습니다. 새 모델 도입 시 먼저 확인합니다.


1. 주제 정의

모델 특성에 따른 프롬프트 는 LLM 의 SFT 학습 구조(Llama 컴플리션 vs ChatML 멀티턴 vs Responses API 4-role)와 어텐션 토큰 위치 효과에 정렬된 프롬프트 작성 전략입니다.

핵심 아이디어: 신경망은 학습된 데이터를 재연하려는 확률 분포이므로, 프롬프트는 모델의 SFT 학습 데이터 분포와 동일한 형태로 구성해야 합니다.


2. 풀려는 문제

실무 LLM 개발에서 다음 4 가지 문제를 해결합니다.

  • 문제 1 — 모델 오작동: Llama 계열의 instruction 슬롯에 상세 지침을 잔뜩 넣으면 학습 분포 밖이라 응답 품질이 급락합니다.
  • 문제 2 — 지침 무시: ChatML 계열의 user 메시지에 지침을 두면 system 보다 영향력이 약해 모델이 지침을 가볍게 처리합니다.
  • 문제 3 — Few-shot 고착화: few-shot 예시를 system 에 넣으면 모델이 예시 답변을 복제하여 일반화 능력이 사라집니다.
  • 문제 4 — API 레거시 락인: Chat Completions 만 사용하면 GPT 최신 기능(reasoning, MCP, 도구 사용 확장)을 활용할 수 없습니다.

💡 실무 노하우: 위 4 문제는 모두 프롬프트 엔지니어링의 문제가 아니라 SFT 학습 구조에 대한 무지에서 발생합니다. 모델 카드/공식 템플릿을 먼저 읽습니다.


3. 핵심 개념·구조

다음 세 요소가 본 단원의 핵심입니다.

  • SFT 학습 구조 (Llama vs ChatML): Llama 계열은 instruction → user → assistant 단일 컴플리션, ChatML 계열은 system → user → assistant 멀티턴.
  • 어텐션 토큰 위치 효과: 앞 토큰은 후속 토큰에 누적 발산 영향, 뒤 토큰은 다음 토큰 분포에 직접 영향. 원래 강도는 뒤가 더 큼.
  • OpenAI Responses API 4-role: instruction(짧은 역할) + developer(상세 지침) + user + assistant. 내부적으로 instruction+developer 가 합쳐져 system 으로 처리됩니다.
Llama  : [INST]<역할>[/INST] <user> => <assistant>
ChatML : system(역할·지침) → user(질의) → assistant(응답)
Resp   : instruction(역할) + developer(상세) → user → assistant
flowchart LR
    A[프롬프트 입력] --> B{모델 SFT 구조}
    B -->|Llama| C[inst 짧게 + user 상세]
    B -->|ChatML| D[system 상세 + user 질의 + few-shot 턴]
    B -->|Responses| E[instruction 짧게 + developer 상세 + user]
    C --> F[정상 응답]
    D --> F
    E --> F

4. 구현 가이드 (Do It Yourself)

시작 전 (Before you begin)

이 섹션 완료하면 4가지 백엔드(Llama·ChatML·Anthropic·Responses API)에 각각 정렬된 프롬프트를 코드로 작성·검증할 수 있습니다.

선수 조건: - Python 3.10+ - pip install anthropic openai transformers - 환경 변수: ANTHROPIC_API_KEY, OPENAI_API_KEY

소요 시간: 약 25분.

Step 1 — Llama 계열 프롬프트 구성

목표: HuggingFace Transformers 의 chat template 으로 Llama 정렬 프롬프트를 생성합니다.

다음 코드를 llama_prompt.py 에 추가합니다.

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B-Instruct")
messages = [
    {"role": "system", "content": "너는 학교 선생님이야."},
    {"role": "user", "content": "이차방정식의 근의 공식을 알려줘."},
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
print(prompt)

이 코드는 Llama 의 공식 chat_template 을 적용해 학습 분포와 동일한 형식의 단일 문자열을 생성합니다.

⚠️ 주의: Llama instruction 슬롯에 상세 지침·제약·입출력 형식을 모두 넣으면 학습한 적 없는 분포라 응답 품질이 급락합니다. 짧은 역할 1~2 문장만 둡니다.

💡 실무 노하우: 모델 카드의 chat_template 을 직접 읽어 보면 SFT 구조를 그대로 확인할 수 있습니다.

📚 참고: HuggingFace Chat Templating 가이드.

확인: print(prompt) 출력에 <|begin_of_text|><|start_header_id|>system<|end_header_id|> 토큰이 포함되어 있으면 정상.


Step 2 — ChatML(GPT) 계열 system 메시지 작성

목표: GPT 계열에 권장되는 5 종 내용(역할·지침·실행 방법·제약·입출력 형식)을 system 에 담습니다.

다음 코드를 chatml_prompt.py 에 추가합니다.

from openai import OpenAI

client = OpenAI()
system = """
역할: 한국어 코드 리뷰어.
지침: PEP8, 보안, 가독성 관점에서 평가.
실행 방법: 문제별 우선순위(상/중/하)와 수정 패치 제시.
제약: 추측 금지, 근거를 코드 라인으로 명시.
출력 형식: 마크다운 표 (라인 / 카테고리 / 우선순위 / 패치).
"""
resp = client.chat.completions.create(
    model="gpt-5",
    messages=[
        {"role": "system", "content": system},
        {"role": "user", "content": "리뷰: def f(x): return x*2"},
    ],
)
print(resp.choices[0].message.content)

이 코드는 ChatML 학습이 강한 system 편향을 부여한다는 점을 활용해, 상세 지침을 system 에 집중시킵니다.

⚠️ 주의: 동일한 5 종 내용을 user 에 두면 system 보다 영향력이 약해 지침이 부분적으로 무시됩니다.

💡 실무 노하우: system 길이가 4K 토큰을 넘으면 모델별 캐시·라우팅 정책이 달라집니다. 프롬프트 캐싱 가격표를 함께 검토합니다.

📚 참고: OpenAI Cookbook Prompt engineering 가이드.

확인: 응답이 마크다운 표 형식이고 라인 번호 근거를 포함하면 system 지침이 적용된 것.


Step 3 — Few-shot 예시를 user/assistant 턴으로 배치

목표: ChatML 계열에서 few-shot 예시를 system 이 아닌 턴으로 구성합니다.

다음 코드를 few_shot.py 에 추가합니다.

messages = [
    {"role": "system", "content": "역할: 영한 번역기. 출력 형식: JSON {ko: ...}"},
    {"role": "user", "content": "Hello"},
    {"role": "assistant", "content": '{"ko": "안녕"}'},
    {"role": "user", "content": "How are you?"},
    {"role": "assistant", "content": '{"ko": "잘 지내?"}'},
    {"role": "user", "content": "Good morning"},
]

이 구조는 모델의 멀티턴 SFT 학습 분포와 정확히 일치합니다.

⚠️ 주의: 예시를 system 에 두면 모델이 지침으로 인식해 동일 질의에 예시 답변을 그대로 복제할 확률이 매우 높아집니다.

💡 실무 노하우: few-shot 2~5 개가 가장 안정적. 10 개 이상은 토큰 비용 대비 효과 체감이 줄어듭니다.

📚 참고: Anthropic Multishot prompting 가이드.

확인: 세 번째 user 질의에 대해 예시 패턴({"ko": ...})을 따르되 내용은 다른 답이 나오면 정상 일반화.


Step 4 — OpenAI Responses API 로 전환

목표: 레거시 Chat Completions 를 Responses API 로 옮기고 4-role 을 활용합니다.

다음 코드를 responses_api.py 에 추가합니다.

from openai import OpenAI

client = OpenAI()
resp = client.responses.create(
    model="gpt-5",
    input=[
        {"role": "developer", "content": "출력 형식: JSON. 추측 금지. 근거 라인 명시."},
        {"role": "user", "content": "PEP8 위반 한 줄 예시?"},
    ],
    instructions="너는 코드 리뷰어다.",
)
print(resp.output_text)

instructions 인자에는 짧은 역할·배경만, developer 메시지에는 상세 제약·입출력 구조·절차를 둡니다.

⚠️ 주의: instructiondeveloper 가 둘 다 system 으로 합쳐지므로, 두 곳에 충돌하는 지시를 두면 동작이 불안정해집니다. 역할은 1곳, 제약은 1곳.

💡 실무 노하우: Responses API 는 reasoning effort, 서버측 도구(MCP·웹검색), 스테이트풀 대화 등 신규 기능을 단독 지원합니다.

📚 참고: OpenAI Responses API 마이그레이션 가이드.

확인: resp.output_text 가 JSON 문자열이고 instructions+developer 의 두 지시가 모두 반영되면 성공.


Step 5 — 동작 확인 (테스트)

import json
# Step 3 결과
assert json.loads(resp.choices[0].message.content)["ko"]  # JSON 형식 강제 확인
# Step 4 결과
assert "PEP8" in resp.output_text or "변수" in resp.output_text
print("✅ 모든 백엔드 정렬 OK")

예상 출력:

✅ 모든 백엔드 정렬 OK

5. 적용 사례 (공신력 오픈소스 5+)

다음 오픈소스가 본 단원의 SFT 정렬·멀티 백엔드 추상화 패턴을 실제로 구현하고 있습니다.

  • LangChain (https://github.com/langchain-ai/langchain) — ChatPromptTemplate, ChatOpenAI/ChatAnthropic 등 백엔드별 어댑터로 추상화.
  • LlamaIndex (https://github.com/run-llama/llama_index) — LLM 추상화로 메시지 → 모델별 chat template 변환.
  • Anthropic Python SDK (https://github.com/anthropics/anthropic-sdk-python) — client.messages.createsystem 파라미터 분리, few-shot 은 messages 턴으로.
  • OpenAI Python SDK (https://github.com/openai/openai-python) — client.responses.createinstructions/developer 롤 분리, client.chat.completions.create 레거시 호환.
  • HuggingFace Transformers (https://github.com/huggingface/transformers) — 각 모델 토크나이저의 chat_template Jinja 로 SFT 구조 그대로 직렬화.
  • vLLM (https://github.com/vllm-project/vllm) — OpenAI 호환 서버에서 chat_template 자동 적용.
  • Ollama (https://github.com/ollama/ollama) — Modelfile TEMPLATE 디렉티브로 모델별 SFT 형식 보관.
  • LiteLLM (https://github.com/BerriAI/litellm) — 100+ 백엔드를 OpenAI Chat Completions 인터페이스로 통일, 내부에서 모델별 변환.
  • Spring AI (https://github.com/spring-projects/spring-ai) — SystemMessage/UserMessage/AssistantMessage 분리, 모델별 어댑터.
  • LangChain4j (https://github.com/langchain4j/langchain4j) — JVM 진영의 동일 추상화. ChatLanguageModel 인터페이스.

📚 참고: 위 OSS 들은 모두 GitHub Stars ≥ 5K 또는 Anthropic·OpenAI·Meta·HuggingFace 공식 SDK 입니다.

💡 실무 노하우: LiteLLM 같은 통합 게이트웨이를 쓰면 백엔드 swap 비용이 거의 0 이 되지만, 각 모델의 SFT 특성을 무시한 일률 변환이 되기 쉽습니다. 중요한 프로덕션 경로는 직접 SDK 사용을 권장.


6. 핵심 원리

가장 중요한 원리 두 가지:

  1. SFT 학습 분포 재연: 신경망은 학습된 데이터 분포의 확률적 재연 장치입니다. 프롬프트가 학습 분포와 다르면 모델은 학습한 적 없는 입력으로 처리하여 품질이 급락합니다.
  2. 어텐션 위치 누적 효과: 앞 토큰은 모든 후속 토큰 생성에 어텐션을 반복 발산하므로 누적 영향이 크고, 뒤 토큰은 다음 토큰 분포에 직접 영향을 줍니다. 원래 강도는 뒤가 더 크지만, ChatML 의 SFT 학습이 앞쪽 system 편향을 강화해 두 효과가 결합됩니다.

7. 변형·확장

  • System 끝 배치 (롱컨텍스트 트릭): 매우 긴 컨텍스트에서 system 영향력이 희석되면 user 마지막에 핵심 제약을 한 번 더 재현합니다.
  • Zero-shot 강제 + 외부 검증: few-shot 없이 system 의 출력 형식 명세 + JSON Schema 검증으로 일반화를 유지합니다.
  • Async / Streaming: SSE 스트리밍으로 첫 토큰 대기 시간을 단축. UX 와 비용 트레이드오프.
  • Batch API: 대량 비동기 작업은 OpenAI Batch / Anthropic Batch 로 50% 비용 절감.

8. 다른 도구·접근과의 비교 (3-way)

  • vs LangChain PromptTemplate — 텍스트 보간 중심. 모델별 SFT 차이를 명시적으로 다루지 않음. ChatPromptTemplate 으로 보완 필요.
  • vs DSPy 시그니처 기반 — 프롬프트를 함수 시그니처로 추상화. SFT 정렬은 컴파일러가 자동 처리. 메타 추상화 수준에서 한 단계 위.
  • vs 직접 chat_template 호출 — HuggingFace tokenizer 의 Jinja 템플릿을 직접 적용. 학습 분포와 가장 가깝지만 멀티 백엔드 코드 양 증가.

9. 한계·트레이드오프

  1. 모델 발전 속도: SFT 학습 방식이 자주 바뀝니다. 가이드는 6 개월 주기로 갱신 필요.
  2. 추상화 vs 정확성: LiteLLM/LangChain 같은 추상화는 코드 양을 줄이지만 모델별 SFT 정렬을 일률 변환해 품질 손실 가능.
  3. 롱컨텍스트 희석: 32K+ 컨텍스트에서 system 영향력이 약해지므로 단순 system 배치만으로 충분하지 않음.
  4. API 마이그레이션 비용: Chat Completions → Responses API 전환 시 라이브러리 호환성과 메시지 스키마 변환 비용이 큽니다.

💡 실무 노하우: Eval 셋(50~200 케이스)으로 마이그레이션 전후 품질 회귀를 측정한 후 전환합니다. promptfoo, OpenAI Evals 등이 도구.


10. 최신 권장 패턴 (2026-05 기준)

  • Responses API 우선 — 신규 OpenAI 프로젝트는 Chat Completions 대신 Responses API. MCP·서버측 도구·reasoning effort 단독 지원.
  • Structured Output / JSON Schemaresponse_format={"type":"json_schema", "schema": ...} 로 출력 형식을 모델 수준에서 강제.
  • Prompt Caching — Anthropic cache_control, OpenAI 자동 캐시로 동일 system 반복 호출 비용 50~90% 절감.
  • Extended Thinking / Reasoning — Claude thinking 파라미터, OpenAI reasoning effort 로 복잡 추론 품질 향상.
  • MCP (Model Context Protocol) — 표준화된 도구·자원 연결 프로토콜. Responses API·Claude Desktop 등이 1차 지원.

11. 메타인지 자기평가

본인 코드·시스템에 적용 가능한지 검증 절차.

Step 1 — 현재 상태 점검

grep -rE "client\.chat\.completions\.create|client\.messages\.create|client\.responses\.create" src/
grep -rE "few.shot|fewshot" prompts/

Step 2 — 적용 가능성 평가

  • 사용 중인 백엔드별 SFT 구조를 알고 있는가? (모델 카드 / chat_template 확인 여부)
  • system 메시지 길이·내용이 모델별로 차별화되어 있는가?
  • few-shot 예시가 system 이 아닌 user/assistant 턴에 있는가?
  • OpenAI 호출이 Responses API 호환 가능한가? (LangChain 등 의존성 점검)

Step 3 — 점진 적용

  1. 모델별 어댑터 함수 1개 작성 (build_messages(provider, ...)).
  2. Eval 셋 50 케이스로 기존 프롬프트 vs 정렬 프롬프트 품질 측정.
  3. 핵심 경로 1개부터 마이그레이션, 회귀 모니터링.
  4. 전사 가이드 문서화 후 점진 확산.

본 학습자료는 SFT 학습 구조·어텐션 위치 효과·OpenAI Responses API 신규 4-role 을 다룹니다. 검증일 2026-05-26, 출처: Anthropic·OpenAI·HuggingFace 공식 문서.

난이도
에피소드
질문
카드를 로딩 중...
답변

클릭하거나 Space를 눌러 뒤집기

0 / 0
학습 진도 0%
이동   Space 뒤집기   R 셔플